package awesomeness.handin1;

public class WeightedQuickUnionUF {
	private int[] id;    // id[i] = parent of i
	private int[] sz;    // sz[i] = number of objects in subtree rooted at i
	private int count;   // number of components
	private int singles; // number of single components
	private boolean hasGiant;

	// Create an empty union find data structure with N isolated sets.
	public WeightedQuickUnionUF(int N) {
		count = N;
		singles = N;
		id = new int[N];
		sz = new int[N];
		for (int i = 0; i < N; i++) {
			id[i] = i;
			sz[i] = 1;
		}
	}

	// Return the number of disjoint sets.
	public int count() {
		return count;
	}

	// Return the size at a given position - our edit
	public int singles() {
		return singles;
	}

	 // Returns if a giant network has been found - our edit
	public boolean hasGiant() {
		return hasGiant;
	}

	// Return component identifier for component containing p
	public int find(int p) {
		while (p != id[p])
			p = id[p];
		return p;
	}

	// Are objects p and q in the same set?
	public boolean connected(int p, int q) {
		return find(p) == find(q);
	}


	// Replace sets containing p and q with their union.
	public void union(int p, int q) {		
		int i = find(p);
		int j = find(q);
		
		if (sz[i] == 1) singles--; // Our edit
		if (sz[j] == 1) singles--; // Our edit
		
		if (i == j) return;
		
		// make smaller root point to larger one
		if   (sz[i] < sz[j]) { id[i] = j; sz[j] += sz[i]; }
		else                 { id[j] = i; sz[i] += sz[j]; }
		count--;

		if (sz[i] > (sz.length / 2) || sz[j] > (sz.length / 2)) hasGiant = true; // Our edit
	}
}